<template>
  <div class="task-execute-view">
    <el-breadcrumb separator="/">
      <el-breadcrumb-item>地铁隧道巡线车智能巡检系统</el-breadcrumb-item>
      <el-breadcrumb-item>
        <router-link to="/task">任务列表</router-link>
      </el-breadcrumb-item>
      <el-breadcrumb-item>任务巡视</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- 顶部右侧数据库开关 -->
    <el-switch
        v-model="settingStore.useDb"
        class="db-switcher"
        active-text="读取数据库"
        inactive-text="实时模式"
        @change="handleDbSwitch"
    />

    <el-row :gutter="20" class="main-area" v-loading="loading">
      <!-- 左侧视频及进度条 -->
      <el-col :span="16" class="content-area">
        <div class="video-area">
          <div v-if="!playerReady" class="video-placeholder">
            正在加载播放器…<br/><small>{{ currentCamLabel }}</small>
          </div>
          <div v-else ref="playerBox" class="player-box"></div>
        </div>

        <!-- 进度条 -->
        <div class="scale-bar-area">
          <div class="scale-bar-wrapper">
            <span class="scale-bar-text start">0m</span>
            <span class="scale-bar-text end">{{ taskInfo?.taskTrip }}m</span>
            <div class="scale-bar">
              <div class="scale-bar-progress" :style="{ width: progressPercent + '%' }"></div>
            </div>
            <!-- 故障标记 -->
            <template v-for="flaw in flaws" :key="flaw.id">
              <div
                  class="scale-bar-item scale-bar-flaw"
                  :class="{ unconfirmed: !flaw.confirmed }"
                  :style="{ left: calcLeft(flaw) }"
                  :title="flaw.flawName"
                  @click="viewFlaw(flaw)"
              >📍</div>
            </template>
            <!-- AGV位置 -->
            <div class="scale-bar-item scale-bar-agv" :style="{ left: progressPercent + '%' }" title="当前位置">🚛</div>
          </div>
        </div>
      </el-col>

      <!-- 右侧侧边栏 -->
      <el-col :span="8" class="sidebar">
        <!-- 控制台 -->
        <el-card shadow="never" class="mb-10">
          <template #header>
            <span>控制台</span>

          </template>
          <div class="control-buttons">
            <el-button @click="refreshStream">刷新监控</el-button>
            <el-select v-model="currentCam" placeholder="选择摄像头" style="width: 120px;">
              <el-option v-for="item in cams" :key="item.value" :label="item.label" :value="item.value"  />
            </el-select>
            <el-button type="success" @click="finishTask" :loading="opLoading">完成巡检</el-button>
            <el-button type="danger" @click="abortTask" :loading="opLoading">终止巡检</el-button>
          </div>
        </el-card>

        <!-- 车辆状态 -->
        <el-card shadow="never" class="mb-10">
          <template #header ">
          车辆状态
          <div style="float: right;">
            <span :class="['status-label', !agvRunning ? 'active-stop' : '']" style="margin-left: 10px;color: #f56c6c;font-weight:bold;">停止</span>
            <el-switch v-model="agvRunning" @change="toggleAgv" style="margin: 0 6px;" />
            <span :class="['status-label', agvRunning ? 'active-run' : '']" style="color: #67c23a;font-weight:bold;">运行</span>
          </div>
</template>
<el-descriptions column="1" border>
<el-descriptions-item label="巡视任务编号">{{ taskInfo?.taskCode }}</el-descriptions-item>
<el-descriptions-item label="车辆系统时间">{{ systemTime }}</el-descriptions-item>
<el-descriptions-item label="已行驶距离">
  <span class="count-animation">{{ distance.toFixed(2) }}</span> 米
</el-descriptions-item>
<el-descriptions-item label="故障总计">{{ flaws.length }}</el-descriptions-item>
<el-descriptions-item label="已确定故障"><span class="confirmed-flaw">{{ confirmedCount }}</span></el-descriptions-item>
<el-descriptions-item label="疑似故障"><span class="unconfirmed-flaw">{{ unconfirmedCount }}</span></el-descriptions-item>
</el-descriptions>
</el-card>

<!-- 故障历史 -->
<el-card shadow="never">
<template #header>故障历史</template>
<el-table :data="flaws" stripe size="small" height="300" @row-click="viewFlaw">
  <el-table-column prop="flawName" label="故障名称">
    <template #default="{ row }">
      <el-link type="primary">{{ row.flawName }}</el-link>
    </template>
  </el-table-column>
  <el-table-column prop="flawType" label="故障类型" width="90" />
  <el-table-column prop="flawDistance" label="位置(m)" width="80" />
  <el-table-column prop="confirmed" label="状态" width="80">
    <template #default="{ row }">
      <el-tag :type="row.confirmed ? 'danger' : row.confirmed === false ? 'info' : 'warning'">
        {{ row.confirmed ? '已确认' : row.confirmed === false ? '误报' : '待确认' }}
      </el-tag>
    </template>
  </el-table-column>

</el-table>
</el-card>
</el-col>
</el-row>

<!-- 故障详情模态框 -->
<el-dialog v-model="detailVisible" title="故障详情" width="60%">
<el-row :gutter="20">
  <el-col :span="16">
    <el-image :src="'http://192.168.2.57/prod-api/file' + selectedFlaw?.flawImageUrl" fit="contain" style="width: 100%; height: 450px">
      <template #error><div class="image-placeholder">暂无图片</div></template>
    </el-image>
  </el-col>
  <el-col :span="8">
    <el-descriptions column="1" border>
      <el-descriptions-item label="故障名称">{{ selectedFlaw?.flawName }}</el-descriptions-item>
      <el-descriptions-item label="故障类型">{{ selectedFlaw?.flawType }}</el-descriptions-item>
      <el-descriptions-item label="故障位置">{{ selectedFlaw?.flawDistance }}m</el-descriptions-item>
      <el-descriptions-item label="确认状态">
        <el-radio-group v-model="confirmValue">
          <el-radio :label="true">属实</el-radio>
          <el-radio :label="false">误报</el-radio>
        </el-radio-group>
      </el-descriptions-item>
      <el-descriptions-item label="补充说明">
        <el-input v-model="remark" type="textarea" rows="4" />
      </el-descriptions-item>
    </el-descriptions>
  </el-col>
</el-row>
<template #footer>
  <el-button @click="detailVisible = false">取 消</el-button>
  <el-button type="primary" @click="saveFlaw" :loading="saving">确 定</el-button>
</template>
</el-dialog>
</div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onBeforeUnmount, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { getTask, liveInfo, endTask, agvForward, agvStop, heartbeat, updateFlaw, upsertFlawDb } from '@/axios/api';
import type { AgvTask, AgvFlaw } from '@/axios/types';

import { ElMessage } from 'element-plus';
import { nextTick } from 'vue';
import { useSetting } from '@/stores/setting';

const route = useRoute();
const router = useRouter();
const taskId = Number(route.params.id);
const loading = ref(false);
const opLoading = ref(false);

const taskInfo = ref<AgvTask>();
const flaws = ref<AgvFlaw[]>([]);
const distance = ref(0);
const progressPercent = ref(0);
const timer = ref<number>();
const systemTime = ref('');

const currentCam = ref('cam1');
const cams = [
  { value: 'cam1', label: '摄像头1' },
  { value: 'cam2', label: '摄像头2' },
  { value: 'cam3', label: '摄像头3' },
  { value: 'cam4', label: '摄像头4' },
];
const currentCamLabel = computed(() => cams.find(c => c.value === currentCam.value)?.label || '摄像头');

const confirmedCount = computed(() => flaws.value.filter(f => f.confirmed).length);
const unconfirmedCount = computed(() => flaws.value.filter(f => !f.confirmed).length);


const agvRunning = ref(true);

// ------------------- EasyPlayer 摄像头播放 -------------------
const playerReady = ref(false);

// 摄像头服务主机（不含路径）
const CAMERA_HOST = 'http://192.168.2.57';
// 摄像头接口前缀
const CAMERA_API = `${CAMERA_HOST}/easy-api`;

// 摄像头设备列表
const cameraDevices = ref<{ id: string; name?: string }[]>([]);

// 根据 currentCam 对应的下标，动态构造视频流 URL
const videoUrl = computed(() => {
  const idx = cams.findIndex(c => c.value === currentCam.value);
  const dev = cameraDevices.value[idx];
  const result = dev ? `${CAMERA_HOST}/webrtc-api/live/${dev.id}_01.flv`: '';
  console.log(result);
  return dev ? `${CAMERA_HOST}/webrtc-api/live/${dev.id}_01.flv` : '';
});

// 获取摄像头列表
const fetchCameraDevices = async () => {
  try {
    const resp = await fetch(`${CAMERA_API}/devices?page=1&size=999&status=&id&name`, {
      headers: {
        'Authorization': 'Basic YWRtaW4xMjM6QWRtaW5AMTIz',
      },
    });
    const result = await resp.json();
    console.log(result);
    // 假设后端返回 { data: [...] }
    cameraDevices.value = Array.isArray(result.items) ? result.items : result;
    console.log(cameraDevices.value);
  } catch (e) {
    console.error('获取摄像头列表失败', e);
  }
};

const fetchTask = async () => {
  loading.value = true;
  try {
    const res = await getTask(taskId);
    taskInfo.value = res.data;
  } finally {
    loading.value = false;
  }
};

const pollLiveInfo = async () => {
  try {
    const res = await liveInfo(taskId);

    if (Array.isArray(res.data)) {
      flaws.value = res.data;

      // ---- 同步到本地数据库 ----
      const promises: Promise<any>[] = [];
      res.data.forEach((f: any) => {
        promises.push(upsertFlawDb(f));
      });
      Promise.all(promises).catch((err) => console.error('同步缺陷到DB失败', err));

    }
  } catch (err) {
    console.error(err);
  }
};

// 轮询 AGV 心跳，更新实时状态
const pollAgvStatus = async () => {
  try {
    const res = await heartbeat();
    console.log(res);
    if (res && res.data) {
      const status = res.data as { sysTime?: string; isRunning?: boolean; currentPosition?: number };

      if (status.sysTime) {
        systemTime.value = status.sysTime;
      }
      if (typeof status.currentPosition === 'number') {
        distance.value = status.currentPosition;
        var percent = (status.currentPosition / Number(taskInfo.value?.taskTrip)) * 100;
        percent = percent > 100?100:percent;
        progressPercent.value = percent < 0?0:percent;
      }
      if (typeof status.isRunning === 'boolean') {
        agvRunning.value = status.isRunning;
      }
    }
  } catch (e) {
    console.error('heartbeat 失败', e);
  }
};

// ---------------- 播放器逻辑 ----------------
const playerBox = ref<HTMLElement>();
let playerInstance: any = null;

// 动态加载 EasyPlayerPro 脚本
const loadEasyPlayer = () => {
  return new Promise<void>((resolve, reject) => {
    if ((window as any).EasyPlayerPro) {
      resolve();
      return;
    }
    import('@/easyPlayer/EasyPlayer-pro.js?url')
        .then(m => {
          const script = document.createElement('script');
          script.src = m.default;
          script.onload = () => resolve();
          script.onerror = () => reject();
          document.body.appendChild(script);
        })
        .catch(reject);
  });
};

const createPlayer = () => {

  if (!playerBox.value) return;

  // 若已存在播放器，先销毁
  if (playerInstance && playerInstance.destroy) {
    playerInstance.destroy();
    playerInstance = null;
  }

  const EP = (window as any).EasyPlayerPro;
  if (!EP) return;

  playerInstance = new EP(playerBox.value, {
    isLive: true,
    hasAudio: false,
    stretch: true,
  });

  if (videoUrl.value) {
    playerInstance.play(videoUrl.value).catch(console.error);
  }
};

// 视频源变化时重新播放
watch(videoUrl, (url) => {
  if (playerInstance && url) {
    playerInstance.play(url).catch(console.error);
  }
});

onMounted(async () => {
  await Promise.all([loadEasyPlayer(), fetchCameraDevices()]);
  playerReady.value = true;
  nextTick(() => {
    createPlayer();
  });
  fetchTask();
  pollLiveInfo();
  pollAgvStatus();
  timer.value = window.setInterval(() => {
    pollLiveInfo();
    pollAgvStatus();
  }, 3000);
});

onBeforeUnmount(() => {

  if (timer.value) clearInterval(timer.value);
  if (playerInstance && playerInstance.destroy) {
    playerInstance.destroy();
    playerInstance = null;
  }
});

const calcLeft = (flaw: AgvFlaw) => {
  if (!taskInfo.value?.taskTrip) return '0%';
  const percent = (Number(flaw.flawDistance || 0) / Number(taskInfo.value.taskTrip)) * 100;
  return `${percent}%`;
};

const refreshStream = () => {
  ElMessage.success('已刷新监控');
};

const toggleAgv = (val: boolean) => {
  if (val) {
    agvForward();
  } else {
    agvStop();
  }
};

const finishTask = async () => {
  opLoading.value = true;
  try {
    await endTask(taskId, false);
    ElMessage.success('任务已完成');
    router.push('/task');
  } finally {
    opLoading.value = false;
  }
};

const abortTask = async () => {
  opLoading.value = true;
  try {
    await endTask(taskId, true);
    ElMessage.success('任务已终止');
    router.push('/task');
  } finally {
    opLoading.value = false;
  }
};

const detailVisible = ref(false);
const selectedFlaw = ref<AgvFlaw>();
const confirmValue = ref<boolean | null>(true);
const remark = ref('');
const saving = ref(false);

const viewFlaw = (flaw: AgvFlaw) => {
  selectedFlaw.value = flaw;
  confirmValue.value = flaw.confirmed ?? true;
  remark.value = flaw.remark || '';
  detailVisible.value = true;
};

// 保存故障确认
const saveFlaw = async () => {
  if (!selectedFlaw.value?.id) return;
  saving.value = true;
  try {
    await updateFlaw({
      ...selectedFlaw.value,
      confirmed: confirmValue.value,
      remark: remark.value,
    });
    ElMessage.success('保存成功');
    detailVisible.value = false;
    await pollLiveInfo();
  } finally {
    saving.value = false;
  }
};

const settingStore = useSetting();

const handleDbSwitch = () => {
  fetchTask();
  pollLiveInfo();
};

</script>


<style scoped>
.task-execute-view {
  padding: 20px;
  position: relative;
}
.main-area {
  margin-top: 20px;
}
.content-area {
  display: flex;
  flex-direction: column;
}
.video-area {
  flex: 0.8;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  height: 60vh;
  position: relative;
}
.video-placeholder {
  text-align: center;
}
.scale-bar-area {
  background: #fafafa;
  border-top: 1px solid #eee;
  padding: 20px;
}
.scale-bar-wrapper {
  position: relative;
  height: 60px;
}
.scale-bar {
  width: 100%;
  height: 8px;
  background: #e4e7ed;
  border-radius: 4px;
  position: relative;
  margin: 26px 0;
}
.scale-bar-progress {
  height: 100%;
  background: #409eff;
  border-radius: 4px;
  transition: width 1s ease;
}
.scale-bar-text {
  position: absolute;
  margin-top: 10px;
  font-size: 12px;
  color: #666;
}
.scale-bar-text.start { left: 0; top: 0; }
.scale-bar-text.end { right: 0; top: 0; }
.scale-bar-item {
  position: absolute;
  top: 18px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  cursor: pointer;
  transform: translateX(-50%);
}
.scale-bar-flaw { background: #f56c6c; color: #fff; }
.scale-bar-flaw.unconfirmed { background: #e6a23c; }
.scale-bar-agv { background: #67c23a; color: #fff; font-size: 14px; animation: pulse 2s infinite; }
@keyframes pulse { 0% { transform: translateX(-50%) scale(1); } 50% { transform: translateX(-50%) scale(1.1); } 100% { transform: translateX(-50%) scale(1); } }
.control-buttons { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
.mb-10 { margin-bottom: 10px;  }
.confirmed-flaw { color: #f56c6c; font-weight: bold; }
.unconfirmed-flaw { color: #e6a23c; font-weight: bold; }

.image-placeholder { color: #bbb; font-size: 14px; text-align: center; }
.player-box {
  width: 100%;
  height: 100%;
}
.active-run { color: #67c23a; font-weight: bold; }
.active-stop{ color:#f56c6c; font-weight:bold;}

.db-switcher {
  position: absolute;
  top: 20px;
  right: 20px;
}
</style>